package views;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import utils.IShowListener;
import utils.SageShowDialog;
import utils.SageTvShows;
import utils.Util;
import alon24sageexternaltools.Activator;
import data.ShowData;

public class SelectedView extends ViewPart implements IShowListener
{
    private Table _table;
    private static LinkedList<ShowData> _shows = new LinkedList<ShowData>();
    private TableViewer _tableViewer;
    public static final String ID = "SelectedView";
    private TableColumn _fileNameCol;
    private TableColumn _newFileNameCol;
    private TableColumn _compressCol;
    private TextCellEditor _tCellEditor;
    private Action deleteItemAction;
    private Action selectAllAction;
    private IMemento memento;
    private SelectedView.SelectedViewLabelProvider _labelProvider;
    private Action _videoRedoAction;
    private static LinkedList<IShowListener> _listeners = new LinkedList<IShowListener>();
    
    private static SelectedView instance = null;

    /**
     * The content provider class is responsible for providing objects to the
     * view. It can wrap existing objects in adapters or simply return objects
     * as-is. These objects may be sensitive to the current input of the view,
     * or ignore it and always show the same content (like Task List, for
     * example).
     */
    class SelectedViewContentProvider implements IStructuredContentProvider
    {
        public void inputChanged(Viewer v, Object oldInput, Object newInput)
        {
        }

        public void dispose()
        {
        }

        public Object[] getElements(Object parent)
        {
            return _shows.toArray();
        }
    }

    class SelectedViewLabelProvider extends LabelProvider implements
            ITableLabelProvider
    {
        public String getColumnText(Object obj, int index)
        {
            ShowData showData = (ShowData) obj;
            switch (index)
            {
                case 0:
                    return showData.getShowId();
                case 1:
                    return showData.getTitle();
                case 2:
                    return showData.getFileName();
                case 3:
                    return showData.getNewFileName();
                case 4:
                    return showData.getHasCompressFile(false).toString();
                case 5:
                    return showData.getHasProjectFile(false).toString();
            }

            return "";
        }

        public Image getColumnImage(Object obj, int index)
        {
            return getImage(obj);
        }

        public Image getImage(Object obj)
        {
            return PlatformUI.getWorkbench().getSharedImages().getImage(
                    ISharedImages.IMG_OBJ_ELEMENT);
        }
    }

    public SelectedView()
    {
        instance = this;
        createActions();
        ShowsView.addShowListener(this);
    }
    
    public static SelectedView getInstance()
    {
        return instance;
    }

    public void init(IViewSite site, IMemento memento) throws PartInitException
    {
        init(site);
        this.memento = memento;
    }
    
    /**
     * Saves the object state within a memento.
     */
    public void saveState(IMemento memento)
    {
        if (_shows == null || _shows.size() == 0)
            return;
        
        memento = memento.createChild("shows");
        for (ShowData show : _shows)
        {
            memento.createChild("descriptor", show.getShowId());
        }
    }

    private void restoreState()
    {
        if (memento == null)
            return;
        
        memento = memento.getChild("shows");
        if (memento != null)
        {
            IMemento descriptors[] = memento.getChildren("descriptor");
            if (descriptors.length > 0)
            {
//                ArrayList<ShowData> objList = new ArrayList<ShowData>(descriptors.length);
                for (int nX = 0; nX < descriptors.length; nX++)
                {
                    String id = descriptors[nX].getID();
                    ShowData data =  SageTvShows.getInstance().getShowDataById(id);
                    if (data != null)
                    {
                        _shows.add(data);
                        sendShowAddedEvent(data);
                    }
                }
                _tableViewer.setInput(_shows);
//                _tableViewer.setSelection(new StructuredSelection(objList));
            }
        }
        memento = null;
        updateActionEnablement();
    }

    private void createActions()
    {
        deleteItemAction = new Action("Delete")
        {
            public void run()
            {
                deleteItem();
            }
        };
        // deleteItemAction.setImageDescriptor(getImageDescriptor("delete.gif"));
        deleteItemAction
                .setImageDescriptor(Util.getImageDescriptor("delete.gif"));
        selectAllAction = new Action("Select All")
        {
            public void run()
            {
                selectAll();
            }
        };
        
        _videoRedoAction  = new Action("VideoRedo")
        {
            public void run()
            {
                videoRedo();
            }
        };
        _videoRedoAction.setImageDescriptor(Util.getImageDescriptor("start.jpg"));
    }

    protected void videoRedo()
    {
        String par = ((ShowData)((StructuredSelection)_tableViewer.getSelection()).getFirstElement()).getFileName();
        try
        {
            String st = Activator.getDefault().getInstalledLocation();
            
//            Process proc = Runtime.getRuntime().exec("C:/work/sage/Alon24SageExternalTools/videoRedo.bat " + par);
            Process proc = Runtime.getRuntime().exec(st + " " + par);
//            proc.waitFor();
        } catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        refreshElementState((ShowData)((StructuredSelection)_tableViewer.getSelection()).getFirstElement());
    }

    protected void deleteItem()
    {
        ISelection sel = _tableViewer.getSelection();
        for (Iterator iterator = ((StructuredSelection)sel).iterator(); iterator.hasNext();)
        {
            Object obj = (Object) iterator.next();
            _tableViewer.remove(obj);
            showRemoved((ShowData) obj);
            sendRemovedShowEvent((ShowData) obj);
        }
        saveState(memento);
    }
    
    public void deleteAll()
    {
        for (Iterator<ShowData> iterator = _shows.iterator(); iterator.hasNext();)
        {
            ShowData show = (ShowData) iterator.next();
            sendRemovedShowEvent(show);
            iterator.remove();
        }
        _tableViewer.getTable().clearAll();
        saveState(memento);
    }

    private void selectAll()
    {
        _tableViewer.getTable().selectAll();
    }

    private void updateActionEnablement()
    {
        IStructuredSelection sel = (IStructuredSelection) _tableViewer
                .getSelection();
        deleteItemAction.setEnabled(sel.size() > 0);
    }

    private void createContextMenu()
    {
        // Create menu manager.
        MenuManager menuMgr = new MenuManager();
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener()
        {
            public void menuAboutToShow(IMenuManager mgr)
            {
                fillContextMenu(mgr);
            }
        });

        // Create menu.
        Menu menu = menuMgr.createContextMenu(_tableViewer.getControl());
        _tableViewer.getControl().setMenu(menu);

        // Register menu for extension.
        getSite().registerContextMenu(menuMgr, _tableViewer);
        getSite().setSelectionProvider(_tableViewer);
    }

    private void fillContextMenu(IMenuManager mgr)
    {
        // mgr.add(addItemAction);
        mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
        mgr.add(deleteItemAction);
        mgr.add(new Separator());
        mgr.add(selectAllAction);
        mgr.add(_videoRedoAction);
    }

    @Override
    public void createPartControl(Composite parent)
    {
        parent.setLayout(new FillLayout(SWT.HORIZONTAL));
        _tableViewer = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
        _tableViewer.setContentProvider(new SelectedViewContentProvider());
        _labelProvider = new SelectedView.SelectedViewLabelProvider();
        _tableViewer
                .setLabelProvider(_labelProvider);
        _table = _tableViewer.getTable();
        _table.setHeaderVisible(true);
        _table.setLinesVisible(true);
        _tCellEditor = new TextCellEditor(_table);
       
        TableColumn showIDCol = new TableColumn(_table, SWT.LEFT);
        showIDCol.setWidth(80);
        showIDCol.setText("ID");
        
        TableColumn showNameCol = new TableColumn(_table, SWT.LEFT);
        showNameCol.setWidth(120);
        showNameCol.setText("name");
        
        TableViewerColumn tableViewerColumn_2 = new TableViewerColumn(
                _tableViewer, SWT.NONE);
        tableViewerColumn_2.setEditingSupport(new EditingSupport(_tableViewer)
        {
            protected boolean canEdit(Object element)
            {
                return true;
            }

            protected CellEditor getCellEditor(Object element)
            {
                return _tCellEditor;
            }

            protected Object getValue(Object element)
            {
                return ((ShowData) element).getFileName();
            }

            protected void setValue(Object element, Object value)
            {
                ((ShowData) element).setFileName((String) value);
            }
        });
        tableViewerColumn_2.setLabelProvider(new ColumnLabelProvider()
        {
            public Image getImage(Object element)
            {
                // TODO Auto-generated method stub
                return null;
            }

            public String getText(Object element)
            {
                return ((ShowData) element).getFileName();
            }
        });
        _fileNameCol = tableViewerColumn_2.getColumn();
        _fileNameCol.setWidth(291);
        _fileNameCol.setText("File name");
        TableViewerColumn tableViewerColumn_3 = new TableViewerColumn(
                _tableViewer, SWT.NONE);
        tableViewerColumn_3.setEditingSupport(new EditingSupport(_tableViewer)
        {
            protected boolean canEdit(Object element)
            {
                return true;
            }

            protected CellEditor getCellEditor(Object element)
            {
                return _tCellEditor;
            }

            protected Object getValue(Object element)
            {
                return ((ShowData) element).getNewFileName();
            }

            protected void setValue(Object element, Object value)
            {
                ((ShowData) element).setNewFileName((String) value);
                _tableViewer.refresh(true);
            }
        });
        tableViewerColumn_3.setLabelProvider(new ColumnLabelProvider()
        {
            public Image getImage(Object element)
            {
                // TODO Auto-generated method stub
                return null;
            }

            public String getText(Object element)
            {
                return ((ShowData) element).getNewFileName();
            }
        });
        _newFileNameCol = tableViewerColumn_3.getColumn();
        _newFileNameCol.setWidth(210);
        _newFileNameCol.setText("New name");
        
        _compressCol = new TableColumn(_table, SWT.LEFT);
        _compressCol.setWidth(80);
        _compressCol.setText(".compress");
        
        TableColumn projectCol = new TableColumn(_table, SWT.LEFT);
        projectCol.setWidth(80);
        projectCol.setText(".project");

        final TableEditor editor = new TableEditor(_table);
        editor.horizontalAlignment = SWT.LEFT;
        editor.grabHorizontal = true;

        _tableViewer.addSelectionChangedListener(new ISelectionChangedListener()
        {
            @Override
            public void selectionChanged(SelectionChangedEvent event)
            {
                updateActionEnablement();
            }
            
        });
        _tableViewer.addDoubleClickListener(new IDoubleClickListener()
        {
            
            @Override
            public void doubleClick(DoubleClickEvent event)
            {
//                videoRedo();
                openShowDialog();
            }
        });
        
        _table.addKeyListener(new KeyListener()
        {
            
            @Override
            public void keyReleased(KeyEvent e)
            {
            }
            
            @Override
            public void keyPressed(KeyEvent e)
            {
                if (e.keyCode == SWT.DEL)
                {
                    deleteItem();
                }
            }
        });
        
        createActions();
        createToolbar();
        createContextMenu();
//        createMenu();
        restoreState();
    }

    protected void openShowDialog()
    {
        ShowData data = (ShowData) ((StructuredSelection) _tableViewer
                .getSelection()).getFirstElement();
        SageShowDialog ssd = new SageShowDialog(this.getSite(), data);
        ssd.open();
    }

    /**
     * Create menu.
     */
    private void createMenu()
    {
        IMenuManager mgr = getViewSite().getActionBars().getMenuManager();
        mgr.add(selectAllAction);
    }

    /**
     * Create toolbar.
     */
    private void createToolbar()
    {
        IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
        // mgr.add(addItemAction);
        mgr.add(deleteItemAction);
        mgr.add(_videoRedoAction);
    }

    @Override
    public void setFocus()
    {
        
    }

    @Override
    public void showAdded(ShowData show)
    {
        if (_shows.contains(show))
        {
            return;
        }
        _shows.add(show);
        show.setInSelectedView(true);
        _tableViewer.setInput(_shows);
//        saveState(memento);
    }
    
    public void addShow(ShowData show)
    {
        LinkedList<ShowData> shows = new LinkedList<ShowData>();
        shows.add(show);
        addShows(shows);
    }
    
    public void addShows(LinkedList<ShowData> shows)
    {
        for (ShowData show : shows)
        {
            if (_shows.contains(show))
            {
                continue;
            }
            _shows.add(show);
            sendShowAddedEvent(show);
        }
        _tableViewer.setInput(_shows);
    }

    @Override
    public void showRemoved(ShowData show)
    {
       //not in use here
    }
    
    @Override
    public void showTransffered(ShowData show)
    {
        if (_shows.contains(show))
        {
            return;
        }
        _shows.add(show);
        show.setInSelectedView(true);
        _tableViewer.setInput(_shows);
    }
    
    public static void addShowListener(IShowListener listener)
    {
        if (_listeners.contains(listener))
            return;
        
        _listeners.add(listener);
        refreshListner(listener);
    }
    
    private static void refreshListner(IShowListener listener)
    {
        for (Iterator<ShowData> iterator = _shows.iterator(); iterator.hasNext();)
        {
            ShowData data = (ShowData) iterator.next();
            sendShowAddedEvent(data);
        }
    }

    /**
     * happens when I need to upfate the showsview view
     * @param show
     */
    private static void sendShowAddedEvent(ShowData show)
    {
        show.setInSelectedView(true);
        for (IShowListener listener : _listeners)
        {
            listener.showAdded(show);
        }
    }
    
    private static void sendRemovedShowEvent(ShowData show)
    {
        show.setInSelectedView(false);
        for (IShowListener listener : _listeners)
        {
            listener.showRemoved(show);
        }
    }
    
    public LinkedList<ShowData> getShows()
    {
        return _shows;
    }
    
    public ISelection getSelection()
    {
        return _tableViewer.getSelection();
    }
    
    private void refreshElementState(ShowData data)
    {
//        data.refreshState();
//        _tableViewer.refresh(data);
    }

    public void refreshShow(ShowData data, ShowData newShowData)
    {
        _shows.remove(data);
        _shows.add(newShowData);
        newShowData.setInSelectedView(true);
        _tableViewer.remove(data);
        _tableViewer.setInput(_shows);
    }
}
